Skip to content

Legion rouge#41

Closed
Dargon789 wants to merge 21 commits into
mainfrom
legion-rouge
Closed

Legion rouge#41
Dargon789 wants to merge 21 commits into
mainfrom
legion-rouge

Conversation

@Dargon789

@Dargon789 Dargon789 commented Mar 14, 2026

Copy link
Copy Markdown
Owner

Summary by Sourcery

Add Merkle tree–based signature verification support and adjust wrapped signature format, updating tests and CI accordingly.

New Features:

  • Support verifying Merkle tree–based signatures that wrap a root digest signature.

Enhancements:

  • Extend wrapped signature encoding to include a merkle flag for conditional Merkle verification.
  • Bump IthacaAccount EIP-712 version to 0.5.11.

CI:

  • Adjust CI to run forge tests while excluding UpgradeTests from the default workflow.

Tests:

  • Add fuzz tests for Merkle-based signatures and invalid proof scenarios.
  • Update existing signature-related tests and gas estimation helpers to use the extended wrapped signature format.

legion2002 and others added 19 commits September 24, 2025 22:22
Add CircleCI configuration file to set up a basic pipeline with a say-hello job and workflow

CI:

Add .circleci/config.yml to define a say-hello job that checks out the code and prints a greeting using the cimg/base Docker image
Add a workflow to orchestrate the say-hello job under the CircleCI 2.1 engine
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
CI:
Update Forge test command to use --rerun and increase verbosity to -vvvvv
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Enhance the CI test step to automatically rerun failed tests and increase verbosity in Forge.
CI:
Enable the --rerun flag for Forge tests to retry failures automatically
Increase Forge test verbosity from -vvv to -vvvvv
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Change Forge test invocation from "forge test --rerun -vvvvv" to "forge test -vvv"
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
This reverts commit 6c02fbf, reversing
changes made to a317ddb.
* Update ci.yaml (#2)

CI:
Update Forge test command to use --rerun and increase verbosity to -vvvvv
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* Update ci.yaml (#4)

Enhance the CI test step to automatically rerun failed tests and increase verbosity in Forge.
CI:
Enable the --rerun flag for Forge tests to retry failures automatically
Increase Forge test verbosity from -vvv to -vvvvv
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* Update ci.yaml (#5)

Change Forge test invocation from "forge test --rerun -vvvvv" to "forge test -vvv"
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* Update ci.yaml

Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* Create CNAME

* Revert "Merge branch 'master'"

This reverts commit 6c02fbf, reversing
changes made to a317ddb.

---------

Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
@vercel

vercel Bot commented Mar 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
legion Canceled Canceled Apr 10, 2026 0:52am

@sourcery-ai

sourcery-ai Bot commented Mar 14, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds Merkle tree–based signature verification support to IthacaAccount, including a new wrapped-signature format, corresponding tests, and CI workflow tweaks to limit test scope, plus a version bump.

Sequence diagram for merkle-based signature verification in IthacaAccount

sequenceDiagram
    actor ExternalCaller
    participant IthacaAccount
    participant MerkleProofLib
    participant EfficientHashLib
    participant ECDSA

    ExternalCaller->>IthacaAccount: unwrapAndValidateSignature(digest, signature)
    activate IthacaAccount

    IthacaAccount->>IthacaAccount: check signature.length
    alt signature.length == 65
        IthacaAccount->>ECDSA: recoverCalldata(digest, signature)
        ECDSA-->>IthacaAccount: signer
        IthacaAccount-->>ExternalCaller: (signer == IthacaAccount, 0)
    else wrapped signature
        IthacaAccount->>IthacaAccount: parse keyHash, prehash, merkle flags via LibBytes
        alt prehash flag set
            IthacaAccount->>EfficientHashLib: sha2(digest)
            EfficientHashLib-->>IthacaAccount: newDigest
            IthacaAccount->>IthacaAccount: digest = newDigest
        end
        alt merkle flag set
            IthacaAccount->>IthacaAccount: _verifyMerkleSig(digest, innerSignature)
            activate IthacaAccount
            IthacaAccount->>IthacaAccount: decode proof, root, rootSig from calldata
            IthacaAccount->>MerkleProofLib: verifyCalldata(proof, root, digest)
            MerkleProofLib-->>IthacaAccount: isLeafInTree
            alt isLeafInTree
                IthacaAccount->>IthacaAccount: unwrapAndValidateSignature(root, rootSig)
                IthacaAccount-->>IthacaAccount: (isValid, keyHash)
                IthacaAccount-->>ExternalCaller: (isValid, keyHash)
            else
                IthacaAccount-->>ExternalCaller: (false, 0)
            end
        else standard wrapped signature flow
            IthacaAccount->>IthacaAccount: key = getKey(keyHash)
            IthacaAccount->>IthacaAccount: validate innerSignature with key
            IthacaAccount-->>ExternalCaller: (isValid, keyHash)
        end
    end
    deactivate IthacaAccount
Loading

Updated class diagram for IthacaAccount merkle signature support

classDiagram
    class IthacaAccount {
        +unwrapAndValidateSignature(bytes32 digest, bytes signature) bool isValid
        +unwrapAndValidateSignature(bytes32 digest, bytes signature) bytes32 keyHash
        -_verifyMerkleSig(bytes32 digest, bytes signature) bool isValid
        -_verifyMerkleSig(bytes32 digest, bytes signature) bytes32 keyHash
        +getKey(bytes32 keyHash) Key
        +_hashTypedData(bytes32 structHash) bytes32
        +_hashTypedDataSansChainId(bytes32 structHash) bytes32
        +getEIP712NameAndVersion() string name
        +getEIP712NameAndVersion() string version
        <<EIP712>>
        <<GuardedExecutor>>
    }

    class MerkleProofLib {
        +verifyCalldata(bytes32[] proof, bytes32 root, bytes32 leaf) bool
    }

    class LibBytes {
        +loadCalldata(bytes data, uint256 index) bytes32
        +truncatedCalldata(bytes data, uint256 newLength) bytes
    }

    class EfficientHashLib {
        +sha2(bytes32 input) bytes32
    }

    class ECDSA {
        +recoverCalldata(bytes32 digest, bytes signature) address
    }

    class Key {
        +address signer
        +bool isValid
    }

    IthacaAccount --> MerkleProofLib : uses
    IthacaAccount --> LibBytes : parses wrappedSignature
    IthacaAccount --> EfficientHashLib : optionalPrehash
    IthacaAccount --> ECDSA : eip191Recover
    IthacaAccount --> Key : authorizationData
Loading

File-Level Changes

Change Details Files
Introduce Merkle tree–based signature verification path and extend wrapped-signature format with a merkle flag.
  • Add MerkleProofLib dependency and internal _verifyMerkleSig helper that decodes proof, root, and root signature from calldata and verifies membership before validating the root signature
  • Extend unwrapAndValidateSignature encoding to abi.encode(innerSignature, keyHash, bool(prehash), bool(merkle)) and adjust parsing logic to read the extra flag and dispatch to _verifyMerkleSig when set
  • Keep existing direct key validation path intact, only gating the new behavior on the merkle flag
  • Bump EIP712 version string from 0.5.10 to 0.5.11 to reflect the new behavior
src/IthacaAccount.sol
Update test helpers and call sites to use the new 4-field wrapped-signature encoding and add dedicated Merkle signature coverage.
  • Append a merkle flag byte (set to 0) to all helper-generated signatures in Base.t.sol and to synthetic signatures in gas estimation / orchestrator / simulate tests so they conform to the new encoding
  • Add testMerkleSignature fuzz test that builds a random Merkle tree using murky/Merkle, generates a proof for a random leaf, and validates expected behavior for valid proofs, invalid digests, tampered proofs, and wrong roots
  • Adjust Account tests to ignore unused eip712Domain fields now that only verifyingContract is needed for domain hashing
test/Base.t.sol
test/Account.t.sol
test/Orchestrator.t.sol
test/SimulateExecute.t.sol
Tighten CI workflow tests to exclude UpgradeTests and add a CNAME file for GitHub Pages configuration.
  • Change CI forge test command to skip UpgradeTests contract to speed up or avoid flaky upgrade tests in standard CI runs
  • Add CNAME file at repository root, likely to configure a custom domain for GitHub Pages or related hosting
.github/workflows/ci.yaml
CNAME

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@snyk-io

snyk-io Bot commented Mar 14, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Ce PR introduit des capacités de vérification de signature Merkle au contrat intelligent IthacaAccount, améliorant ainsi ses mécanismes d'authentification. Il ajoute également un domaine personnalisé pour le déploiement et inclut des tests complets pour la nouvelle logique de signature Merkle, ainsi que des ajustements mineurs à l'encodage des signatures dans les utilitaires de test.

Highlights

  • Vérification de signature Merkle: Introduction de la vérification de signature Merkle dans le contrat IthacaAccount pour des mécanismes d'authentification améliorés.
  • Domaine personnalisé: Ajout d'un fichier CNAME pour configurer un domaine personnalisé legion-rouge.vercel.app.
  • Mise à jour de la version du contrat: La version du contrat IthacaAccount a été mise à jour de 0.5.10 à 0.5.11.
  • Tests de signature Merkle: Ajout de tests complets pour la fonctionnalité de signature Merkle, couvrant les preuves valides, invalides et falsifiées.
Changelog
  • CNAME
    • Ajout du domaine personnalisé legion-rouge.vercel.app.
  • src/IthacaAccount.sol
    • Importation de MerkleProofLib de solady/utils/MerkleProofLib.sol.
    • Ajout de la fonction interne _verifyMerkleSig pour la vérification des signatures Merkle.
    • Mise à jour de la fonction unwrapAndValidateSignature pour prendre en charge les signatures Merkle en décodant un nouveau drapeau merkle.
    • Incrémentation de la version du contrat de 0.5.10 à 0.5.11.
  • test/Account.t.sol
    • Importation de la bibliothèque Merkle de murky/Merkle.sol.
    • Ajout de la fonction de test testMerkleSignature pour valider la logique de vérification de signature Merkle.
    • Ajustement de la déstructuration de la valeur de retour de eip712Domain() pour exclure name et version.
  • test/Base.t.sol
    • Modification des fonctions _p256Sig, _secp256k1Sig, _multiSig, _estimateGasForEOAKey, et _estimateGasForSecp256r1Key pour inclure un octet supplémentaire uint8(0) dans l'encodage de la signature, afin de prendre en charge le nouveau drapeau merkle.
  • test/Orchestrator.t.sol
    • Ajustement de l'encodage de la signature dans la fonction _estimateGas pour inclure un octet supplémentaire uint8(0).
  • test/SimulateExecute.t.sol
    • Ajustement de l'encodage de la signature dans la fonction _estimateGas pour inclure un octet supplémentaire uint8(0).
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/ci.yaml
Activity
  • Aucune activité n'a été enregistrée pour cette pull request.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@Dargon789

Copy link
Copy Markdown
Owner Author

@Mergifyio refresh

@Dargon789

Copy link
Copy Markdown
Owner Author

@Mergifyio update

@mergify

mergify Bot commented Mar 14, 2026

Copy link
Copy Markdown

refresh

✅ Pull request refreshed

@mergify

mergify Bot commented Mar 14, 2026

Copy link
Copy Markdown

update

⚠️ Cannot use the command update

Details

⚠ The product Workflow Automation needs to be activated to enable this feature.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In _verifyMerkleSig, the inline assembly assumes a well‑formed abi.encode(bytes32[] proof, bytes32 root, bytes rootSig) payload with no minimal length or bounds checks; consider adding basic length/offset validation before reading from calldata to avoid undefined behavior on malformed or adversarial merkle signatures.
  • The new wrapped signature format adds a merkle flag byte but unwrapAndValidateSignature still truncates signature before reading both the prehash and merkle flags; this relies on LibBytes.loadCalldata ignoring the truncated length and may be brittle—consider reading the two flag bytes before truncating or documenting this invariant clearly.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `_verifyMerkleSig`, the inline assembly assumes a well‑formed `abi.encode(bytes32[] proof, bytes32 root, bytes rootSig)` payload with no minimal length or bounds checks; consider adding basic length/offset validation before reading from calldata to avoid undefined behavior on malformed or adversarial merkle signatures.
- The new wrapped signature format adds a merkle flag byte but `unwrapAndValidateSignature` still truncates `signature` before reading both the prehash and merkle flags; this relies on `LibBytes.loadCalldata` ignoring the truncated length and may be brittle—consider reading the two flag bytes before truncating or documenting this invariant clearly.

## Individual Comments

### Comment 1
<location path="src/IthacaAccount.sol" line_range="542-549" />
<code_context>
+        bool merkle;
         unchecked {
-            uint256 n = signature.length - 0x21;
+            uint256 n = signature.length - 0x22;
             keyHash = LibBytes.loadCalldata(signature, n);
             signature = LibBytes.truncatedCalldata(signature, n);
             // Do the prehash if last byte is non-zero.
             if (uint256(LibBytes.loadCalldata(signature, n + 1)) & 0xff != 0) {
                 digest = EfficientHashLib.sha2(digest); // `sha256(abi.encode(digest))`.
             }
+            merkle = uint256(LibBytes.loadCalldata(signature, n + 2)) & 0xff != 0;
+        }
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Flag bytes are read after truncating the signature, leading to out-of-bounds reads and incorrect offsets.

With the current layout (`abi.encode(bytes(innerSignature), bytes32(keyHash), bool(prehash), bool(merkle))`), the trailing fields are at:
- `keyHash`: `len - 34 .. len - 3`
- `prehash`: `len - 2`
- `merkle`: `len - 1`

You set `n = len - 34`, then truncate `signature` to length `n`, but still read at `n + 1` and `n + 2`. After truncation `signature.length == n`, so these reads are past the end of the slice and no longer match the documented layout.

Instead, compute all positions from the original `len` and read flags before truncating, e.g.:
```solidity
uint256 len = signature.length;
uint256 keyPos = len - 34;
uint256 prehashPos = len - 2;
uint256 merklePos = len - 1;

keyHash = LibBytes.loadCalldata(signature, keyPos);
bool prehash = uint256(LibBytes.loadCalldata(signature, prehashPos)) & 0xff != 0;
merkle = uint256(LibBytes.loadCalldata(signature, merklePos)) & 0xff != 0;

signature = LibBytes.truncatedCalldata(signature, keyPos);
```
This keeps offsets consistent and avoids out-of-bounds reads.
</issue_to_address>

Fix all in Cursor


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/IthacaAccount.sol

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for Merkle tree–based signatures, a significant enhancement to the account's verification capabilities. The implementation adds a new verification path in IthacaAccount.sol and extends the wrapped signature format with a merkle flag. The changes are well-supported by tests, including a new fuzz test for Merkle signature validation that covers various scenarios. Existing tests have been correctly updated to accommodate the new signature format. My review found a minor documentation issue in IthacaAccount.sol regarding the encoding of the wrapped signature, which I've commented on. Overall, the changes are robust and well-implemented.

Comment thread src/IthacaAccount.sol
@vercel

This comment was marked as resolved.

@Dargon789

Copy link
Copy Markdown
Owner Author

@Mergifyio rebase

@mergify

mergify Bot commented Mar 14, 2026

Copy link
Copy Markdown

rebase

⚠️ Cannot use the command rebase

Details

⚠ The product Workflow Automation needs to be activated to enable this feature.

@Dargon789 Dargon789 enabled auto-merge (squash) March 14, 2026 23:49
@Dargon789 Dargon789 linked an issue Apr 7, 2026 that may be closed by this pull request
@Dargon789

Copy link
Copy Markdown
Owner Author

@Mergifyio rebase

1 similar comment
@Dargon789

Copy link
Copy Markdown
Owner Author

@Mergifyio rebase

@mergify

mergify Bot commented Apr 7, 2026

Copy link
Copy Markdown

rebase

☑️ Command rebase ignored because it is already running from a previous command.

@mergify

mergify Bot commented Apr 7, 2026

Copy link
Copy Markdown

rebase

⚠️ Cannot use the command rebase

Details

⚠ The product Workflow Automation needs to be activated to enable this feature.

@Dargon789

Copy link
Copy Markdown
Owner Author

@Mergifyio refresh

1 similar comment
@Dargon789

Copy link
Copy Markdown
Owner Author

@Mergifyio refresh

@Dargon789 Dargon789 disabled auto-merge April 7, 2026 14:10
@Dargon789 Dargon789 enabled auto-merge (rebase) April 7, 2026 14:10
@mergify

mergify Bot commented Apr 7, 2026

Copy link
Copy Markdown

refresh

☑️ Command refresh ignored because it is already running from a previous command.

@mergify

mergify Bot commented Apr 7, 2026

Copy link
Copy Markdown

refresh

✅ Pull request refreshed

Remove executable bit from deploy/execute_config.sh, deploy/verify_config.sh, and prep/check-bytecode-changes.js (mode 100755 → 100644). Update lib/forge-std submodule from commit c2cf7017d27c1d20e74ace4dacb6c5ce4bbbe899 to 07853315f998f94dc724e464b1bab1270888ee64. No other content changes.
@Dargon789

Copy link
Copy Markdown
Owner Author

@Mergifyio refresh

@mergify

mergify Bot commented Apr 10, 2026

Copy link
Copy Markdown

refresh

✅ Pull request refreshed

@Dargon789 Dargon789 closed this Apr 10, 2026
auto-merge was automatically disabled April 10, 2026 00:56

Pull request was closed

This was referenced Apr 11, 2026
@sourcery-ai sourcery-ai Bot mentioned this pull request Apr 20, 2026
@sourcery-ai sourcery-ai Bot mentioned this pull request Apr 20, 2026
@sourcery-ai sourcery-ai Bot mentioned this pull request May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sequence diagram for wrapped and Merkle signature validation

4 participants